package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.leyou.common.dto.*;
import com.leyou.common.exception.MyException;
import com.leyou.common.utils.JsonUtils;
import com.leyou.item.entity.Category;
import com.leyou.item.entity.Sku;
import com.leyou.item.entity.Spu;
import com.leyou.item.entity.SpuDetail;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.SkuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SpuService extends ServiceImpl<SpuMapper, Spu> implements com.leyou.item.service.SpuService {
    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SpecGroupService groupService;

    @Autowired
    private SpecParamService paramService;

    @Autowired
    private SpuDetailService detailService;
    @Autowired
    private SkuService skuService;
    @Override
    public PageDTO<SpuDTO> queryByPage(Integer page, Integer rows, Boolean saleable, Long categoryId, Long brandId, Long id) {
        IPage<Spu> iPage = new Page<>(page,rows);

        //select * from tb_spu [where saleable = xx ,] limit x,y
        page(iPage,new QueryWrapper<Spu>()
                .eq(null!=saleable,"saleable",saleable)
                .eq(null!=brandId,"brand_id",brandId)
                .eq(null!=categoryId,"cid3",categoryId)
                .eq(null!=id,"id",id)
        );

        List<SpuDTO> spuDTOS = SpuDTO.convertEntityList(iPage.getRecords());
        spuDTOS.forEach(spuDTO -> {
            //根据分类id的集合查询对应的分类集合，并取出分类名称并拼接为字符串
            String name = this.categoryService.listByIds(spuDTO.getCategoryIds())
                    .stream().map(Category::getName)
                    .collect(Collectors.joining("/"));
            spuDTO.setCategoryName(name);
            //根据brandId查询对应的品牌
            spuDTO.setBrandName(this.brandService.getById(spuDTO.getBrandId()).getName());

        });
        //封装spu的分页查询结果
        return new PageDTO<>(iPage.getTotal(),iPage.getPages(),spuDTOS);
    }

    @Override
    @Transactional
    public void updateSable(Long id, Boolean saleable) {
        // 1.更新SPU
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        boolean success = updateById(spu);
        if(!success){
            throw new MyException(500, "更新失败");
        }
        // 2.更新sku
         success = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        if (!success) {
            throw new MyException(500, "更新失败");
        }
    }

    @Override
    public List<SpecParamDTO> querySpecValues(Long spuId, Boolean searching) {

        //获取分类ID
        Long cid = getById(spuId).getCid3();
        List<SpecParamDTO> specParamDTOS = SpecParamDTO.convertEntityList(this.paramService
                .query()
                .eq("category_id", cid)
                .eq(null != searching, "searching",searching)
                .list());
        //获取规格参数的value，
        SpuDetail spuDtail = detailService.getById(spuId);
        Map<Long, Object> valueMap  = JsonUtils.nativeRead(spuDtail.getSpecification(), new TypeReference<Map<Long, Object>>(){

        });
        //遍历specParamDTO，给每个value赋值，每个value的值，就是valuemap的value
        specParamDTOS.forEach(specParamDTO -> {
            //规格参数的id
            Long key = specParamDTO.getId();
            Object o = valueMap.get(key);
            specParamDTO.setValue(o);
        });
        return specParamDTOS;
    }

    @Override
    public SpuDTO queryGoods(Long spuId) {
        List<SpuDTO> spuDTOS = queryByPage(1, 1, null, null, null, spuId).getItems();
        if (CollectionUtils.isEmpty(spuDTOS)) {
            throw new MyException(204, "对应商品不存在");
        }
        List<SkuDTO> skuDTOS = skuService.querySkuBySpuId(spuId);
        SpuDetailDTO spuDetailDTO = detailService.queryDetailById(spuId);
        SpuDTO spuDTO = spuDTOS.get(0);
       spuDTO.setSkus(skuDTOS);
       spuDTO.setSpuDetail(spuDetailDTO);
        return spuDTO;
    }

    @Override
    public SpuDTO querySpuBuId(Long id) {
        Spu spu = getById(id);

        return new SpuDTO(spu);
    }

    @Override
    public void saveGoods(SpuDTO spuDTO) {
        // 1.新增Spu
        Spu spu = spuDTO.toEntity(Spu.class);
        spu.setSaleable(false);
        boolean success = save(spu);
        if (!success) {
            throw new MyException(500, "新增商品失败");
        }
        // 2.新增SpuDetail
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        spuDetail.setSpuId(spu.getId());
        success=detailService.save(spuDetail);
        if (!success) {
            throw new MyException(500, "新增商品失败");
        }
        List<Sku> list=
        spuDTO.getSkus().stream().map(skuDTO -> {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSaleable(false);
            sku.setSpuId(spu.getId());
            return sku;
        }).collect(Collectors.toList());
        // 批量新增
        skuService.saveBatch(list);
    }

    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
        // 1.修改spu
        // 1.1.判断是否存在spu的id，有说明需要修改，没有说明不需要
        Long spuId = spuDTO.getId();
        if (spuId != null) {
            Spu spu = spuDTO.toEntity(Spu.class);
            boolean success = updateById(spu);
            if (!success) {
                throw new MyException(500, "商品更新失败");
            }
        }
        List<SkuDTO> dtoList = spuDTO.getSkus();
        if (CollectionUtils.isEmpty(dtoList)) {
            return;
        }
        //转换DTO，并将sku根据saleable是否为null来分组。null，是新增或修改，不是null是删除
        Map<Boolean, List<Sku>> map =dtoList.stream()
                .map(skuDTO -> skuDTO.toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));
        // 获取要新增或修改的sku
        List<Sku> insertOrUpdateList = map.get(true);
        // 如果不为空，则修改或新增
        if (!CollectionUtils.isEmpty(insertOrUpdateList)) {
            skuService.saveOrUpdateBatch(insertOrUpdateList);
        }
        List<Sku> deleteSkuList = map.get(false);
        if (!CollectionUtils.isEmpty(deleteSkuList)) {
            // 存在要删除的sku
            List<Long> idList = deleteSkuList.stream().map(Sku::getId).collect(Collectors.toList());
            // 删除
            skuService.removeByIds(idList);

        }
    }
}
